/**
 * 服务容器 - 依赖注入管理
 * 
 * 优势：
 * 1. 完全控制实例创建时机
 * 2. 避免循环依赖
 * 3. 便于测试和 mock
 * 4. 统一管理所有单例
 * 
 * @author AI Assistant
 * @date 2025-11-27
 */

/**
 * 服务生命周期
 */
export enum ServiceLifetime {
    /** 单例 - 全局唯一实例 */
    Singleton = 'singleton',
    /** 瞬时 - 每次请求都创建新实例 */
    Transient = 'transient',
    /** 作用域 - 在特定作用域内共享实例 */
    Scoped = 'scoped'
}

/**
 * 服务描述符
 */
interface ServiceDescriptor<T = any> {
    /** 服务标识 */
    token: string | symbol;
    /** 工厂函数 */
    factory: () => T;
    /** 生命周期 */
    lifetime: ServiceLifetime;
    /** 缓存的实例（用于单例） */
    instance?: T;
}

/**
 * 服务容器
 */
export class ServiceContainer {
    private static _instance: ServiceContainer;
    
    /** 服务注册表 */
    private services = new Map<string | symbol, ServiceDescriptor>();
    
    /** 作用域实例缓存 */
    private scopedInstances = new Map<string | symbol, any>();
    
    private constructor() {}
    
    /**
     * 获取全局容器实例
     */
    static getInstance(): ServiceContainer {
        if (!this._instance) {
            this._instance = new ServiceContainer();
        }
        return this._instance;
    }
    
    /**
     * 注册单例服务
     */
    registerSingleton<T>(
        token: string | symbol,
        factory: () => T
    ): void {
        this.services.set(token, {
            token,
            factory,
            lifetime: ServiceLifetime.Singleton
        });
    }
    
    /**
     * 注册瞬时服务
     */
    registerTransient<T>(
        token: string | symbol,
        factory: () => T
    ): void {
        this.services.set(token, {
            token,
            factory,
            lifetime: ServiceLifetime.Transient
        });
    }
    
    /**
     * 直接注册实例（用于已存在的对象）
     */
    registerInstance<T>(
        token: string | symbol,
        instance: T
    ): void {
        this.services.set(token, {
            token,
            factory: () => instance,
            lifetime: ServiceLifetime.Singleton,
            instance
        });
    }
    
    /**
     * 解析服务
     */
    resolve<T>(token: string | symbol): T {
        const descriptor = this.services.get(token);
        
        if (!descriptor) {
            throw new Error(`服务未注册: ${String(token)}`);
        }
        
        switch (descriptor.lifetime) {
            case ServiceLifetime.Singleton:
                // 单例：如果已创建则复用
                if (!descriptor.instance) {
                    descriptor.instance = descriptor.factory();
                }
                return descriptor.instance as T;
                
            case ServiceLifetime.Transient:
                // 瞬时：每次都创建新实例
                return descriptor.factory() as T;
                
            case ServiceLifetime.Scoped:
                // 作用域：在当前作用域内复用
                let scopedInstance = this.scopedInstances.get(token);
                if (!scopedInstance) {
                    scopedInstance = descriptor.factory();
                    this.scopedInstances.set(token, scopedInstance);
                }
                return scopedInstance as T;
                
            default:
                throw new Error(`未知的生命周期: ${descriptor.lifetime}`);
        }
    }
    
    /**
     * 尝试解析服务（不存在则返回 null）
     */
    tryResolve<T>(token: string | symbol): T | null {
        try {
            return this.resolve<T>(token);
        } catch {
            return null;
        }
    }
    
    /**
     * 检查服务是否已注册
     */
    has(token: string | symbol): boolean {
        return this.services.has(token);
    }
    
    /**
     * 清除作用域缓存
     */
    clearScope(): void {
        this.scopedInstances.clear();
    }
    
    /**
     * 重置容器（用于测试）
     */
    reset(): void {
        this.services.clear();
        this.scopedInstances.clear();
    }
    
    /**
     * 获取所有已注册的服务
     */
    getRegisteredServices(): string[] {
        return Array.from(this.services.keys()).map(k => String(k));
    }
}

/**
 * 全局容器实例
 */
export const container = ServiceContainer.getInstance();

/**
 * 服务标识符（使用 Symbol 避免冲突）
 */
export const Services = {
    SceneCoordinator: Symbol('SceneCoordinator'),
    GameApplication: Symbol('GameApplication'),
    WorldSystem: Symbol('WorldSystem'),
    FixedUpdateManager: Symbol('FixedUpdateManager'),
    CommandQueue: Symbol('CommandQueue'),
    Logger: Symbol('Logger'),
} as const;

/**
 * 装饰器：自动注册为单例服务
 */
export function Injectable(token: string | symbol) {
    return function <T extends { new(...args: any[]): {} }>(constructor: T) {
        container.registerSingleton(token, () => new constructor());
        return constructor;
    };
}

/**
 * 示例用法：
 * 
 * ```typescript
 * // 1. 注册服务
 * container.registerSingleton(Services.SceneCoordinator, () => new SceneCoordinator());
 * 
 * // 2. 使用服务
 * const coordinator = container.resolve<SceneCoordinator>(Services.SceneCoordinator);
 * coordinator.init(sceneRoot);
 * 
 * // 3. 使用装饰器（自动注册）
 * @Injectable(Services.SceneCoordinator)
 * class SceneCoordinator {
 *     // ...
 * }
 * ```
 */

